using Microsoft.Extensions.Logging;
using System.Text.Json;
using System.Collections.Concurrent;
using SumerCoreDevOps.Domain.Entities;
using SumerCoreDevOps.Infrastructure.Data;
using SumerCoreDevOps.Shared.Models.Messages;
using SumerCoreDevOps.Shared.Enums;
using TaskStatus = SumerCoreDevOps.Shared.Enums.TaskStatus;

namespace SumerCoreDevOps.Infrastructure.Workflow;

/// <summary>
/// 工作流引擎 - 核心调度器
/// </summary>
public class WorkflowEngine
{
    private readonly FreeSQLProvider _dbProvider;
    private readonly WorkflowDefinitionManager _definitionManager;
    private readonly WorkflowInstanceTracker _instanceTracker;
    private readonly ILogger<WorkflowEngine> _logger;
    private readonly ConcurrentDictionary<long, CancellationTokenSource> _runningWorkflows = new();

    public event Func<WorkflowStepDispatchMessage, Task>? OnStepDispatch;

    public WorkflowEngine(
        FreeSQLProvider dbProvider,
        WorkflowDefinitionManager definitionManager,
        WorkflowInstanceTracker instanceTracker,
        ILogger<WorkflowEngine> logger)
    {
        _dbProvider = dbProvider;
        _definitionManager = definitionManager;
        _instanceTracker = instanceTracker;
        _logger = logger;
    }

    /// <summary>
    /// 执行工作流
    /// </summary>
    public async Task<long> ExecuteWorkflowAsync(
        long pipelineId,
        string? commitHash = null,
        string? commitMessage = null,
        string? triggeredBy = null)
    {
        // 获取流水线配置
        var pipeline = await _dbProvider.Orm.Select<Pipeline>()
            .Where(p => p.Id == pipelineId)
            .Include(p => p.WorkflowDefinition)
            .FirstAsync();

        if (pipeline == null)
        {
            throw new InvalidOperationException($"流水线 {pipelineId} 不存在");
        }

        if (!pipeline.IsEnabled)
        {
            throw new InvalidOperationException($"流水线 {pipelineId} 已禁用");
        }

        // 获取工作流定义
        var workflow = await _definitionManager.GetWorkflowWithDetailsAsync(pipeline.WorkflowDefinitionId);
        if (workflow == null)
        {
            throw new InvalidOperationException($"工作流定义 {pipeline.WorkflowDefinitionId} 不存在");
        }

        // 验证工作流定义
        var (isValid, errors) = await _definitionManager.ValidateWorkflowAsync(workflow.Id);
        if (!isValid)
        {
            throw new InvalidOperationException($"工作流定义验证失败: {string.Join(", ", errors)}");
        }

        // 生成构建编号
        int buildNumber = await GenerateBuildNumberAsync(pipelineId);

        // 创建流水线实例
        var instance = await _instanceTracker.CreateInstanceAsync(
            pipelineId,
            buildNumber,
            commitHash,
            commitMessage,
            triggeredBy);

        // 启动工作流执行
        var cts = new CancellationTokenSource();
        _runningWorkflows.TryAdd(instance.Id, cts);

        _ = Task.Run(async () =>
        {
            try
            {
                await ExecuteWorkflowInstanceAsync(instance.Id, workflow, cts.Token);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "工作流执行失败: InstanceId={InstanceId}", instance.Id);
                await _instanceTracker.CompleteInstanceAsync(instance.Id, TaskStatus.Failed);
            }
            finally
            {
                _runningWorkflows.TryRemove(instance.Id, out _);
            }
        }, cts.Token);

        _logger.LogInformation("启动工作流执行: PipelineId={PipelineId}, InstanceId={InstanceId}, BuildNumber={BuildNumber}",
            pipelineId, instance.Id, buildNumber);

        return instance.Id;
    }

    /// <summary>
    /// 取消工作流执行
    /// </summary>
    public async Task CancelWorkflowAsync(long instanceId)
    {
        if (_runningWorkflows.TryRemove(instanceId, out var cts))
        {
            cts.Cancel();
            await _instanceTracker.CancelInstanceAsync(instanceId);
            _logger.LogInformation("取消工作流: InstanceId={InstanceId}", instanceId);
        }
    }

    /// <summary>
    /// 执行工作流实例
    /// </summary>
    private async Task ExecuteWorkflowInstanceAsync(
        long instanceId,
        WorkflowDefinition workflow,
        CancellationToken cancellationToken)
    {
        await _instanceTracker.StartInstanceAsync(instanceId);

        var context = new Dictionary<string, string>();

        try
        {
            // 按顺序执行阶段
            foreach (var stage in workflow.Stages.OrderBy(s => s.Order))
            {
                cancellationToken.ThrowIfCancellationRequested();

                // 检查触发条件
                if (!await EvaluateTriggerConditionAsync(stage, context))
                {
                    _logger.LogInformation("跳过阶段: {StageName}, 触发条件不满足", stage.Name);
                    continue;
                }

                _logger.LogInformation("开始执行阶段: {StageName}", stage.Name);

                // 根据执行模式执行步骤
                if (stage.ExecutionMode == ExecutionMode.Serial)
                {
                    await ExecuteStepsSerialAsync(instanceId, stage, context, cancellationToken);
                }
                else
                {
                    await ExecuteStepsParallelAsync(instanceId, stage, context, cancellationToken);
                }

                _logger.LogInformation("完成执行阶段: {StageName}", stage.Name);
            }

            // 所有阶段完成
            await _instanceTracker.CompleteInstanceAsync(instanceId, TaskStatus.Success);
            _logger.LogInformation("工作流执行成功: InstanceId={InstanceId}", instanceId);
        }
        catch (OperationCanceledException)
        {
            await _instanceTracker.CompleteInstanceAsync(instanceId, TaskStatus.Cancelled);
            _logger.LogWarning("工作流被取消: InstanceId={InstanceId}", instanceId);
        }
        catch (Exception ex)
        {
            await _instanceTracker.CompleteInstanceAsync(instanceId, TaskStatus.Failed);
            _logger.LogError(ex, "工作流执行失败: InstanceId={InstanceId}", instanceId);
            throw;
        }
    }

    /// <summary>
    /// 串行执行步骤
    /// </summary>
    private async Task ExecuteStepsSerialAsync(
        long instanceId,
        Stage stage,
        Dictionary<string, string> context,
        CancellationToken cancellationToken)
    {
        foreach (var step in stage.Steps.OrderBy(s => s.Order))
        {
            cancellationToken.ThrowIfCancellationRequested();
            await ExecuteStepAsync(instanceId, step, context, cancellationToken);
        }
    }

    /// <summary>
    /// 并行执行步骤
    /// </summary>
    private async Task ExecuteStepsParallelAsync(
        long instanceId,
        Stage stage,
        Dictionary<string, string> context,
        CancellationToken cancellationToken)
    {
        var tasks = stage.Steps.Select(step =>
            ExecuteStepAsync(instanceId, step, context, cancellationToken));

        await Task.WhenAll(tasks);
    }

    /// <summary>
    /// 执行单个步骤
    /// </summary>
    private async Task ExecuteStepAsync(
        long instanceId,
        Step step,
        Dictionary<string, string> context,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("执行步骤: {StepName}, StepId={StepId}", step.Name, step.Id);

        // 创建任务记录
        var task = new TaskEntity
        {
            PipelineInstanceId = instanceId,
            StepId = step.Id,
            Status = TaskStatus.Pending
        };

        task.Id = (long)await _dbProvider.Orm.Insert(task).ExecuteIdentityAsync();

        // 构建步骤下发消息
        var dispatchMessage = new WorkflowStepDispatchMessage
        {
            TaskId = task.Id,
            StepId = step.Id,
            StepType = step.StepType,
            StepConfig = step.StepConfig,
            Command = step.Command,
            WorkDirectory = $"/tmp/sumer-devops/{instanceId}/{task.Id}",
            TimeoutSeconds = step.TimeoutSeconds,
            RetryPolicy = step.MaxRetries > 0 ? new RetryPolicy
            {
                MaxRetries = step.MaxRetries,
                RetryIntervalSeconds = step.RetryIntervalSeconds
            } : null,
            Context = new Dictionary<string, string>(context),
            EncryptedCredentials = new Dictionary<CredentialType, string>()
        };

        // 触发步骤下发事件
        if (OnStepDispatch != null)
        {
            await OnStepDispatch(dispatchMessage);
        }

        // 等待任务完成（实际项目中会通过消息机制接收任务状态）
        // 这里简化处理，实际需要等待执行节点上报状态
        _logger.LogInformation("步骤已下发: {StepName}, TaskId={TaskId}", step.Name, task.Id);
    }

    /// <summary>
    /// 评估触发条件
    /// </summary>
    private async Task<bool> EvaluateTriggerConditionAsync(
        Stage stage,
        Dictionary<string, string> context)
    {
        if (string.IsNullOrEmpty(stage.TriggerCondition))
        {
            return true; // 无条件，始终执行
        }

        try
        {
            var condition = JsonSerializer.Deserialize<Dictionary<string, string>>(stage.TriggerCondition);
            if (condition == null) return true;

            // 简单的键值匹配逻辑
            foreach (var (key, value) in condition)
            {
                if (!context.TryGetValue(key, out var contextValue) || contextValue != value)
                {
                    return false;
                }
            }

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "评估触发条件失败: {TriggerCondition}", stage.TriggerCondition);
            return false;
        }

        await Task.CompletedTask;
    }

    /// <summary>
    /// 生成构建编号
    /// </summary>
    private async Task<int> GenerateBuildNumberAsync(long pipelineId)
    {
        var maxBuildNumber = await _dbProvider.Orm.Select<PipelineInstance>()
            .Where(i => i.PipelineId == pipelineId)
            .MaxAsync(i => (int?)i.BuildNumber);

        return (maxBuildNumber ?? 0) + 1;
    }

    /// <summary>
    /// 更新任务状态（由任务调度器调用）
    /// </summary>
    public async Task UpdateTaskStatusAsync(
        long taskId,
        TaskStatus status,
        int progress,
        string? errorMessage = null,
        Dictionary<string, string>? outputContext = null)
    {
        var updateQuery = _dbProvider.Orm.Update<TaskEntity>()
            .Set(t => t.Status, status)
            .Set(t => t.Progress, progress)
            .Where(t => t.Id == taskId);

        if (status == TaskStatus.Running)
        {
            var hasStartTime = await _dbProvider.Orm.Select<TaskEntity>()
                .Where(t => t.Id == taskId && t.StartTime != null)
                .AnyAsync();

            if (!hasStartTime)
            {
                updateQuery.Set(t => t.StartTime, DateTime.UtcNow);
            }
        }

        if (status == TaskStatus.Success || status == TaskStatus.Failed || status == TaskStatus.Cancelled)
        {
            updateQuery.Set(t => t.EndTime, DateTime.UtcNow);
        }

        if (!string.IsNullOrEmpty(errorMessage))
        {
            updateQuery.Set(t => t.ErrorMessage, errorMessage);
        }

        if (outputContext != null)
        {
            updateQuery.Set(t => t.OutputContext, JsonSerializer.Serialize(outputContext));
        }

        await updateQuery.ExecuteAffrowsAsync();

        _logger.LogInformation("更新任务状态: TaskId={TaskId}, Status={Status}, Progress={Progress}",
            taskId, status, progress);
    }
}
